package com.terrynoya.fight.combat
{
	import com.terrynoya.fight.animations.Clsn;
	import com.terrynoya.fight.char.Character;
	import com.terrynoya.fight.char.Entity;
	import com.terrynoya.fight.data.parser.sff.SpriteItem;
	import com.terrynoya.fight.emuns.ClsnType;
	import com.terrynoya.fight.system.camera.MCamera;
	import com.terrynoya.fight.system.camera.MCameraController;
	import com.terrynoya.fight.system.camera.MCameraItem;
	import com.terrynoya.fight.util.Misc;
	import com.terrynoya.geom.MVector2D;
	
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.geom.Rectangle;

	public class FightStage extends EngineObject
	{
		private var _width:int;
		private var _height:int;
		
		private var _worldLayer:Sprite;
		private var _backgroundLayer:Sprite;
		private var _characterLayer:Sprite;
		private var _debugLayer:Sprite;
		
		private var _name:String;
		private var _cameraStartLocation:MVector2D;
		
		private var _cameraContrl:MCameraController;
		private var _zOffset:int;
		private var _leftEdgeDistance:int;
		private var _rightEdgeDistance:int;
		
		private var _cameraPosition:MVector2D;
		
		private var _tension:int;
		
		/**
		 * 游戏分辨率为320*240
		 * if stageBg 为 495*260
		 * then boundleft = (495 - 320)/2;
		 * 		boundHeight = 240 - 260; 
		 */		
		private var _cameraBounds:Rectangle;
		
		private var _bgView:SpriteItem;
		
		public function FightStage(engine:FightEngine,bgView:SpriteItem,stageWidth:int = 495,stageHeight:int = 260,viewPortWidth:int = 320,viewPortHeight:int = 240)
		{
			super(engine);
			
			this._cameraPosition = new MVector2D();
			
			this._bgView = bgView;
			this._cameraContrl = new MCameraController(stageWidth,stageHeight,viewPortWidth,viewPortHeight);
			this._worldLayer = new Sprite();
			this._backgroundLayer = new Sprite();
			this._characterLayer = new Sprite(); 
			this._debugLayer = new Sprite();
			
			this._worldLayer.addChild(this._backgroundLayer);
			this._worldLayer.addChild(this._characterLayer);
			this._worldLayer.addChild(this._debugLayer);
			
			this._backgroundLayer.addChild(this._bgView.view);
			this._cameraStartLocation = new MVector2D();
			this._width = stageWidth;
			this._height = stageHeight;
		}

		public function get tension():int
		{
			return _tension;
		}

		public function set tension(value:int):void
		{
			_tension = value;
		}

		public function get rightEdgeDistance():int
		{
			return _rightEdgeDistance;
		}

		public function set rightEdgeDistance(value:int):void
		{
			_rightEdgeDistance = value;
		}

		public function get leftEdgeDistance():int
		{
			return _leftEdgeDistance;
		}

		public function set leftEdgeDistance(value:int):void
		{
			_leftEdgeDistance = value;
		}

		public function get zOffset():int
		{
			return _zOffset;
		}

		public function set zOffset(value:int):void
		{
			_zOffset = value;
		}

		public function get cameraContrl():MCameraController
		{
			return _cameraContrl;
		}

		public function get characterLayer():Sprite
		{
			return _characterLayer;
		}

		public function get render():Sprite
		{
			return _worldLayer;
		}

		public function get height():int
		{
			return _height;
		}

		public function set height(value:int):void
		{
			_height = value;
		}

		public function get width():int
		{
			return _width;
		}

		public function set width(value:int):void
		{
			_width = value;
		}
		
		public function update():void
		{
			this.moveCameraTo(this.getCameraMovement());
			this.moveCameraTo(this.getCameraMovement());
			this.renderCameraItem();
		}
		
		private function moveCameraTo(delta:MVector2D):void
		{
			var cap:int = 5;
			
			delta.x = Misc.clamp(delta.x, -cap,cap);
			delta.y = Misc.clamp(delta.y, -cap,cap);
			
			this._cameraPosition = this._cameraPosition.add(delta);
			
			var trueCamPos:MVector2D = new MVector2D(this._width,this._height).scale(0.5).add(this._cameraPosition);
			this._cameraContrl.moveCameraTo(trueCamPos);
			
			this.initCameraItem();
			this._cameraContrl.update();
			
			var bgPos:MVector2D = this._cameraContrl.globalToCamera(new MVector2D());
			this._bgView.view.x = bgPos.x;
			this._bgView.view.y = bgPos.y;
			this.drawCamera();
		}
		
		private function getCameraMovement():MVector2D
		{
			var left:Number = this.getLeftmostCharacterAdjustment();
			var right:Number = this.getRightmostCharacterAdjustment();
			var delta:MVector2D = new MVector2D(left + right , 0);
			return delta;
		}
		
		private function getLeftmostCharacterAdjustment():Number
		{
			var chara:Character = this.getLeftMostCharacter();
			if(chara == null)
			{
				return 0;
			}
			
			var camera:MCamera = this.cameraContrl.camera;
			var xPos:Number = chara.getLeftEdgePosition(true) - camera.x;
			var leftMost:Number = xPos + (camera.width / 2 - this.tension);
			var rlt:Number = leftMost < 0 ? leftMost : 0;
			return rlt;
		}
		
		private function getRightmostCharacterAdjustment():Number
		{
			var chara:Character = this.getRightMostCharacter();
			if(chara == null)
			{
				return 0;
			}
			var camera:MCamera = this.cameraContrl.camera;
			var xPos:Number = chara.getRightEdgePosition(true) - camera.x;
			var rightMost:Number = xPos - (camera.width / 2 - this.tension);
			var rlt:Number = rightMost > 0 ? rightMost : 0;
			return rlt;
		}
		
		private function getLeftMostCharacter():Character
		{
			var chara:Entity = null;
			var minPos:MVector2D = new MVector2D(this.stage.width,0);
			var entites:EntityCollection = this.engine.entities;
			for (var i:int = 0; i < entites.length; i++) 
			{
				var entity:Entity = entites.getChildAt(i);
				if(entity.position.x < minPos.x)
				{
					chara = entity;
					minPos = entity.position;
				}
			}
			return chara as Character;
		}
		
		private function getRightMostCharacter():Character
		{
			var chara:Entity = null;
			var maxPos:MVector2D = new MVector2D(0,0);
			var entites:EntityCollection = this.engine.entities;
			for (var i:int = 0; i < entites.length; i++) 
			{
				var entity:Entity = entites.getChildAt(i);
				if(entity.position.x > maxPos.x)
				{
					chara = entity;
					maxPos = entity.position;
				}
			}
			return chara as Character;
		}
		
		private function renderCameraItem():void
		{
			var items:Array = this._cameraContrl.items;
			for (var i:int = 0; i < items.length; i++) 
			{
				var item:MCameraItem = items[i];
				var entity:Entity = item.data as Entity;
				entity.draw();
			}
		}
		
		private function drawFrame():void
		{
			var g:Graphics = this._debugLayer.graphics;
			g.clear();
			g.lineStyle(1);
			this.drawCollision(g);
			g.lineStyle(1,0);
			g.drawRect(0,0,this.width,this.height);
			g.endFill();
		}
		
		private function drawCamera():void
		{
			var g:Graphics = this._debugLayer.graphics;
			g.clear();
			g.lineStyle(1,0xffff00);
			g.drawRect(0,0,this._cameraContrl.camera.width,this._cameraContrl.camera.height);
			g.endFill();
		}
		
		private function initCameraItem():void
		{
			this._cameraContrl.clear();
			var entities:EntityCollection = this.engine.entities;
			for (var i:int = 0; i < entities.length; i++) 
			{
				var entity:Entity = entities.getChildAt(i);
				var item:MCameraItem = new MCameraItem(entity);
				item.position = entity.position;
				this._cameraContrl.addItem(item);
			}
		}
		
		private function drawCollision(g:Graphics):void
		{
			for (var i:int = 0; i < this.engine.entities.length; i++) 
			{
				var chara:Character = Character(this.engine.entities.getChildAt(i));
				var rects:Array = chara.collision.globalCollison;
				if(rects == null)
				{
					continue;
				}
				for (var j:int = 0; j < rects.length; j++) 
				{
					var clsn:Clsn = rects[j];
					var rect:Rectangle = clsn.rect;
					var rectColor:uint = clsn.type == ClsnType.Type2Normal ? 0x999933 : 0x0000ff;
					g.lineStyle(1,rectColor);
					g.drawRect(rect.x,rect.y,rect.width,rect.height);
				}
			}
		}

	}
}